package com.ruoyi.project.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.StringUtils;

import com.ruoyi.framework.web.domain.TreeSelect;

import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysDictType;
import com.ruoyi.project.system.domain.SysDirTree;

import com.ruoyi.project.system.domain.SysRole;
import com.ruoyi.project.system.mapper.SysDictTypeMapper;
import com.ruoyi.project.system.mapper.SysDirTreeMapper;
import com.ruoyi.project.system.mapper.SysRoleMapper;
import com.ruoyi.project.system.service.ISysDirTreeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统目录树 服务实现类
 * </p>
 *
 * @author luaj
 * @since 2019-11-22
 */
@Service
public class SysDirTreeServiceImpl extends ServiceImpl<SysDirTreeMapper, SysDirTree> implements ISysDirTreeService {
    @Autowired
    private SysDirTreeMapper sysDirTreeMapper;
    
    @Autowired
    private SysDictTypeMapper sysDictTypeMapper;
    
    @Autowired
    private SysRoleMapper sysRoleMapper;


    /**
     * 查询目录管理数据
     *
     * @param dirTree 目录信息
     * @return 目录信息集合
     */
    @Override
    public List<SysDirTree> selectSysDirTreeList(SysDirTree dirTree)
    {
        return sysDirTreeMapper.selectList(new QueryWrapper<SysDirTree>(dirTree).orderByAsc("parent_id"));
    }

    /**
     * 构建前端所需要树结构
     *
     * @param dirTreeList 目录列表
     * @return 树结构列表
     */
    @Override
    public List<SysDirTree> builddirTreeTree(List<SysDirTree> dirTreeList)
    {
        List<SysDirTree> returnList = new ArrayList<SysDirTree>();
        for (Iterator<SysDirTree> iterator = dirTreeList.iterator(); iterator.hasNext();)
        {
            SysDirTree t = (SysDirTree) iterator.next();
            // 根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (t.getParentId() == 0)
            {
                recursionFn(dirTreeList, t);
                returnList.add(t);
            }
        }
        if (returnList.isEmpty())
        {
            returnList = dirTreeList;
        }
        return returnList;
    }

    /**
     * 构建前端所需要下拉树结构
     *
     * @param dirTreeList 目录列表
     * @return 下拉树结构列表
     */
    @Override
    public List<TreeSelect> builddirTreeTreeSelect(List<SysDirTree> dirTreeList)
    {
        List<SysDirTree> dirTreeTrees = builddirTreeTree(dirTreeList);
        return dirTreeTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
    }


    /**
     * 根据目录ID查询信息
     *
     * @param dirTreeId 目录ID
     * @return 目录信息
     */
    @Override
    public SysDirTree selectdirTreeById(Long dirTreeId)
    {
        return sysDirTreeMapper.selectById(dirTreeId);
    }

    /**
     * 是否存在子节点
     *
     * @param dirTreeId 目录ID
     * @return 结果
     */
    @Override
    public boolean hasChildBydirTreeId(Long dirTreeId)
    {
        int result = sysDirTreeMapper.selectCount(Wrappers.<SysDirTree>lambdaQuery().eq(SysDirTree::getParentId, dirTreeId));
        return result > 0 ? true : false;
    }

    /**
     * 查询目录下是否存在角色或字典
     *
     * @param dirTreeId 目录ID
     * @return 结果 true 存在 false 不存在
     */
    @Override
    public boolean checkdirTreeExistChild(Long dirTreeId)
    {
        int result=0;
        result = sysRoleMapper.selectCount(Wrappers.<SysRole>lambdaQuery().eq(SysRole::getParentId, dirTreeId));
        if(result>0)
            return true;
        result=sysDictTypeMapper.selectCount(Wrappers.<SysDictType>lambdaQuery().eq(SysDictType::getParentId,dirTreeId));
        if(result>0)
            return true;
        return false;
    }



    /**
     * 校验目录名称是否唯一
     *
     * @param dirTree 目录信息
     * @return 结果
     */
    @Override
    public String checkdirTreeNameUnique(SysDirTree dirTree)
    {
        Long dirId = StringUtils.isNull(dirTree.getDirId()) ? -1L : dirTree.getDirId();
        SysDirTree info = sysDirTreeMapper.selectOne(Wrappers.<SysDirTree>lambdaQuery().eq(SysDirTree::getDirName,dirTree.getDirName()).eq(SysDirTree::getParentId,dirTree.getParentId()));
        if (StringUtils.isNotNull(info) && info.getDirId().longValue() != dirId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    /**
     * 新增保存目录信息
     *
     * @param dirTree 目录信息
     * @return 结果
     */
    @Override
    public int insertdirTree(SysDirTree dirTree)
    {
        SysDirTree info = sysDirTreeMapper.selectOne(Wrappers.<SysDirTree>lambdaQuery().eq(SysDirTree::getDirId, dirTree.getParentId()));
        // 如果父节点不为正常状态,则不允许新增子节点
        if (!UserConstants.DIRTREE_NORMAL.equals(info.getStatus().toString()))
        {
            throw new CustomException("目录停用，不允许新增");
        }
        dirTree.setAncestors(info.getAncestors() + "," + dirTree.getParentId());
        dirTree.setCreateTime(new Date());
        return sysDirTreeMapper.insert(dirTree);
    }

    /**
     * 修改保存目录信息
     *
     * @param dirTree 目录信息
     * @return 结果
     */
    @Override
    public int updatedirTree(SysDirTree dirTree)
    {

        SysDirTree newParentdirTree = sysDirTreeMapper.selectById(dirTree.getParentId());
        SysDirTree olddirTree = sysDirTreeMapper.selectById(dirTree.getDirId());
        if (StringUtils.isNotNull(newParentdirTree) && StringUtils.isNotNull(olddirTree))
        {
            String newAncestors = newParentdirTree.getAncestors() + "," + newParentdirTree.getDirId();
            String oldAncestors = olddirTree.getAncestors();
            dirTree.setAncestors(newAncestors);
            updatedirTreeChildren(dirTree.getDirId(), newAncestors, oldAncestors);
        }
        int result = sysDirTreeMapper.updateById(dirTree);
        if (UserConstants.DIRTREE_NORMAL.equals(dirTree.getStatus().toString()))
        {
            // 如果该目录是启用状态，则启用该目录的所有上级目录
            updateParentdirTreeListtatus(dirTree);
        }
        return result;
    }

    /**
     * 修改该目录的父级目录状态
     *
     * @param dirTree 当前目录
     */
    private void updateParentdirTreeListtatus(SysDirTree dirTree)
    {
        String updateBy = dirTree.getUpdateBy();
        dirTree = sysDirTreeMapper.selectById(dirTree.getDirId());
        dirTree.setUpdateBy(updateBy);
        dirTree.setUpdateTime(new Date());
        UpdateWrapper<SysDirTree> updateWrapper=new UpdateWrapper<>();
        updateWrapper.in("dir_id",dirTree.getAncestors().split(","));
        SysDirTree sysDirTree=new SysDirTree();
        sysDirTree.setStatus(Integer.valueOf(UserConstants.DIRTREE_NORMAL));
        sysDirTreeMapper.update(sysDirTree,updateWrapper);
    }

    /**
     * 修改子元素关系
     *
     * @param dirTreeId 被修改的目录ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    public void updatedirTreeChildren(Long dirTreeId, String newAncestors, String oldAncestors)
    {
        List<SysDirTree> children = sysDirTreeMapper.selectChildrendirTreeById(dirTreeId);
        for (SysDirTree child : children)
        {
            child.setAncestors(child.getAncestors().replace(oldAncestors, newAncestors));
        }
        if (children.size() > 0)
        {
            sysDirTreeMapper.updateDirTreeChildren(children);
        }
    }

    /**
     * 删除目录管理信息
     *
     * @param dirTreeId 目录ID
     * @return 结果
     */
    @Override
    public int deletedirTreeById(Long dirTreeId)
    {
        return sysDirTreeMapper.deleteById(dirTreeId);
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysDirTree> list, SysDirTree t)
    {
        // 得到子节点列表
        List<SysDirTree> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDirTree tChild : childList)
        {
            if (hasChild(list, tChild))
            {
                // 判断是否有子节点
                Iterator<SysDirTree> it = childList.iterator();
                while (it.hasNext())
                {
                    SysDirTree n = (SysDirTree) it.next();
                    recursionFn(list, n);
                }
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<SysDirTree> getChildList(List<SysDirTree> list, SysDirTree t)
    {
        List<SysDirTree> tlist = new ArrayList<SysDirTree>();
        Iterator<SysDirTree> it = list.iterator();
        while (it.hasNext())
        {
            SysDirTree n = (SysDirTree) it.next();
            if (n.getParentId().longValue() == t.getDirId().longValue())
            {
                tlist.add(n);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChild(List<SysDirTree> list, SysDirTree t)
    {
        return getChildList(list, t).size() > 0 ? true : false;
    }


}
